package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author atguigu-mqx
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${ware.url}")
    private String wareUrl;  // wareUrl = http://localhost:9001

    @Autowired
    private RabbitService rabbitService;



    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {
        //  编写插入数据实现！
        //  需要赋值的字段： total_amount order_status user_id out_trade_no trade_body expire_time process_status
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //  第三方交易编号 保证唯一！
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);

        orderInfo.setTradeBody("啤酒饮料矿泉水,花生,瓜子,八宝粥。来来来把腿收一收..");
        //  expire_time 24 小时！
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE,1);
        orderInfo.setExpireTime(calendar.getTime());
        orderInfo.setOperateTime(new Date());
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        orderInfoMapper.insert(orderInfo);

        //  插入订单明细！
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        orderDetailList.forEach(orderDetail -> {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        });
        //  获取订单Id
        Long orderId = orderInfo.getId();
        //  发送消息：
        this.rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,MqConst.ROUTING_ORDER_CANCEL,orderId,MqConst.DELAY_TIME);
        //  返回订单Id
        return orderId;
    }

    @Override
    public String getTradeNo(String userId) {
        //  生成一个流水号！
        String tradeNo = UUID.randomUUID().toString();
        //  使用哪种数据类型：
        String tradeNoKey = "tradeNo:"+userId;
        this.redisTemplate.opsForValue().set(tradeNoKey,tradeNo);
        //  返回！
        return tradeNo;
    }

    @Override
    public Boolean checkTradeNo(String tradeNo, String userId) {
        //  生成key
        String tradeNoKey = "tradeNo:"+userId;
        String tradeNoRedis = (String) this.redisTemplate.opsForValue().get(tradeNoKey);
        //  返回比较结果
        //        if (tradeNo.equals(tradeNoRedis)){
        //            return true;
        //        }else {
        //            return false;
        //        }
        return tradeNo.equals(tradeNoRedis);
    }

    @Override
    public void delTradeNo(String userId) {
        //  生成key
        String tradeNoKey = "tradeNo:"+userId;
        this.redisTemplate.delete(tradeNoKey);
    }

    @Override
    public Boolean checkStock(Long skuId, Integer skuNum) {
        //   wareUrl = http://localhost:9001
        //  调用接口：http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        //  返回值！
        return "1".equals(result);
    }

    @Override
    public IPage<OrderInfo> getOrderPageList(Page queryPage, String userId) {
        //  查询什么数据是根据页面显示决定的！ order_info order_detail;
        IPage<OrderInfo> iPage = orderInfoMapper.selectPageByUserId(queryPage,userId);
        //  根据订单的状态来获取订单的名称！
        iPage.getRecords().forEach((orderInfo)->{
            orderInfo.setOrderStatusName(OrderStatus.getStatusNameByStatus(orderInfo.getOrderStatus()));
        });
        //  返回数据
        return iPage;
    }

    @Override
    public void cancelOrder(Long orderId) {
        //  创建订单对象
        //        OrderInfo orderInfo = new OrderInfo();
        //        orderInfo.setId(orderId);
        //        orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
        //        orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
        //        orderInfoMapper.updateById(orderInfo);
        this.updateOrderStatus(orderId,ProcessStatus.CLOSED);

    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        //  获取订单信息：
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo!=null){
            //  获取订单明细：
            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id", orderId));
            //  赋值信息
            orderInfo.setOrderDetailList(orderDetailList);
        }
        return orderInfo;
    }

    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        //  从进度状态中获取订单状态！
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public void sendOrderStatus(Long orderId) {
        //  修改订单状态！
        this.updateOrderStatus(orderId,ProcessStatus.NOTIFIED_WARE);
        //  根据订单Id来获取orderInfo{orderDetail}发送消息！
        OrderInfo orderInfo = this.getOrderInfo(orderId);

        //        JSONObject jsonObject = new JSONObject();
        //        jsonObject.put("orderId",orderInfo.getId());
        //  将orderInfo 部分数据变为map 集合
        //        HashMap<String, Object> map = new HashMap<>();
        //        map.put("orderId",orderInfo.getId());
        //        map.put("consignee",orderInfo.getConsignee());

        //  将orderInfo 部分数据变为map 集合
        Map<String,Object> map = this.initWare(orderInfo);

        //  将map 变为Json 字符串！
        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,MqConst.ROUTING_WARE_STOCK, JSON.toJSONString(map));
    }

    //  将orderInfo 部分数据变为map 集合
    public Map<String, Object> initWare(OrderInfo orderInfo) {
        //  声明一个map 集合
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");
        //  map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！
        //  details:[{skuId:101,skuNum:1,skuName:’小米手64G’},{skuId:201,skuNum:1,skuName:’索尼耳机’}]
        //  获取到订单明细！
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //        List<Map> maps = new ArrayList<>();
        //        for (OrderDetail orderDetail : orderDetailList) {
        //            HashMap<String, Object> detailMap = new HashMap<>();
        //            detailMap.put("skuId",orderDetail.getSkuId());
        //            detailMap.put("skuNum",orderDetail.getSkuNum());
        //            detailMap.put("skuName",orderDetail.getSkuName());
        //            maps.add(detailMap);
        //        }
        List<HashMap<String, Object>> maps = orderDetailList.stream().map((orderDetail) -> {
            HashMap<String, Object> detailMap = new HashMap<>();
            detailMap.put("skuId", orderDetail.getSkuId());
            detailMap.put("skuNum", orderDetail.getSkuNum());
            detailMap.put("skuName", orderDetail.getSkuName());
            return detailMap;
        }).collect(Collectors.toList());
        //  添加订单明细！
        map.put("details",maps);
        //  返回map 集合！
        return map;
    }
}
